/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.ufc.quixada.adrs.comandos.visit;

import br.ufc.quixada.adrs.interfaces.Comando;
import br.ufc.quixada.adrs.model.Movimentacao;
import br.ufc.quixada.adrs.model.Produtor;
import br.ufc.quixada.adrs.model.TipoAnimal;
import br.ufc.quixada.adrs.model.Visita;
import br.ufc.quixada.adrs.service.TipoAnimalService;
import br.ufc.quixada.adrs.util.Msg;
import br.ufc.quixada.adrs.util.UtilAdrs;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 *
 * @author Escritorio projetos
 */
public class CmdVisitRelatorioProdutoresPorMovimentacoes implements Comando {

    final String ROUBADOS = "ROUBADOS";
    final String NASCIDOS = "NASCIDOS";
    final String MORTOS = "MORTOS";
    final String COMPRADOS = "COMPRADOS";
    final String VENDIDOS = "VENDIDOS";

    public String executa(HttpServletRequest request, HttpServletResponse response) {
        HttpSession session = request.getSession(true);
        List<Produtor> produtoresSelecionados = (ArrayList<Produtor>) session.getAttribute("produtoresSelecionadoQS");
        List<String> tiposMovSelecionadas = new ArrayList<String>();
        //recuperar dados do formulário
        String todosPeriodos = request.getParameter("todosPeriodos");
        String dataIni = request.getParameter("dataInicio");
        String dataFim = request.getParameter("dataFim");
        String selectOperacao = request.getParameter("operacao");
        String sValor = request.getParameter("valor");
        //pega o tipo de animal
        String sTipoAnimal = (String) request.getParameter("tipoAnimal");
        //boolean para indicar se todos os períodos foram marcados ou não.
        boolean tdPeriodosSelected = false;
        if (todosPeriodos != null) {
            tdPeriodosSelected = true;
        }
        //validações dos campos.
        if (!tdPeriodosSelected) {
            if (!UtilAdrs.validaData(dataIni)) {
                session.setAttribute("erro", Msg.INPUT_ERROR_WRONG_START_DATE_FORMAT);
                return "/visit/visit_relatorio_passo_4_filtros_movims.jsp";
            } else if (!UtilAdrs.validaData(dataFim)) {
                session.setAttribute("erro", Msg.INPUT_ERROR_WRONG_END_DATE_FORMAT);
                return "/visit/visit_relatorio_passo_4_filtros_movims.jsp";
            }
        }
        if (!UtilAdrs.isNumber(sValor)) {
            session.setAttribute("erro", Msg.NOT_NUMERIC_VALOR);
            return "/visit/visit_relatorio_passo_4_filtros_movims.jsp";
        }
        boolean hasDoencaComboBoxSelected = request.getParameter("cb_movim") != null ? true : false;
        if (hasDoencaComboBoxSelected) {
            String arrayMovimentacoesComboBox[] = request.getParameterValues("cb_movim");
            for (int i = 0; i < arrayMovimentacoesComboBox.length; i++) {
                tiposMovSelecionadas.add(arrayMovimentacoesComboBox[i]);
            }
        } else {
            session.setAttribute("erro", Msg.EMPTY_SELECTION_ERROR_MOVIMENTACAO);
            return "/visit/visit_relatorio_passo_4_filtros_movims.jsp";
        }
        //guarda o tipo de animal marcado na tela
        TipoAnimal tAnimal = null;

        //um booleano que indica se o todos os animais foi marcado ou não
        boolean todosOstiposAnimais = true;

        //se não foi marcado o booleano recebe falso e guardamos o tipo marcado no objeto tAnimal
        if (!sTipoAnimal.equalsIgnoreCase("todos")) {
            todosOstiposAnimais = false;
            Long idTipo = Long.parseLong(sTipoAnimal);
            tAnimal = new TipoAnimalService().getTipoAnimalById(idTipo);
            sTipoAnimal = tAnimal.getTipo();
        }


        //Datas de inicio e fim do relatório
        Date ini = UtilAdrs.treatToDate(dataIni);
        Date fim = UtilAdrs.treatToDate(dataFim);


        /**
         * Seleção dos produtores que serão exibidos no relatório. Estarão nesse relatório os produtores que possuem 
         * todas as ocorrências de movimentação obedececendo os critérios estabelecidos na consulta.
         */
        List<Produtor> produtoresResult = new ArrayList<Produtor>();
        for (Produtor produtor : produtoresSelecionados) {
            //Vetor que totaliza o número de ocorrencia das doencas para aquele produtor.
            Integer[] qtdeMovimentacoes = new Integer[tiposMovSelecionadas.size()];
            for (int k = 0; k < qtdeMovimentacoes.length; k++) {
                qtdeMovimentacoes[k] = new Integer(0);
            }
            //Serão selecionadas as visitas com questionários sanitários respondidos.
            List<Visita> visitas = produtor.getVisitas();
            for (Visita visita : visitas) {
                if (!visita.hasQuestionarioQuantitativo()) {
                    continue;
                }
                /**
                 * As doenças serão contabilizadas se a opçao todos os períodos foi selecionada,
                 * ou, do contrário, se a visita foi realizada dentro do período especificado.
                 */
                if (tdPeriodosSelected || (!tdPeriodosSelected && visita.visitaBetweenInitialDateAndFinalDate(ini, fim))) {
                    for (int j = 0; j < tiposMovSelecionadas.size(); j++) {
                        String sMovimentacao = tiposMovSelecionadas.get(j);
                        for (Movimentacao movTemp : visita.getQuestionarioQuantitativo().getMovimentacoes()) {
                            if (todosOstiposAnimais) {
                                qtdeMovimentacoes[j] += getOcorrenciasDaMovimentacao(movTemp, sMovimentacao);
                            } else if (tAnimal != null) {
                                qtdeMovimentacoes[j] += getOcorrenciasDaMovimentaçaoPorTipoAnimal(movTemp, tAnimal, sMovimentacao);
                            }
                        }
                    }
                }
            }
            //O produtor será mostrado no resultado se satisfizer as condições da consulta
            if (isCompatibleWithCondtions(qtdeMovimentacoes, selectOperacao, Integer.parseInt(sValor))) {
                produtoresResult.add(produtor);
            }
        }

        //Exibir qual periodo foi marcado
        String periodo = "de " + UtilAdrs.getPrimeiraDataQuestionario(produtoresSelecionados) + " a " + UtilAdrs.getUltimaDataQuestionario(produtoresSelecionados);
        if (!tdPeriodosSelected) {
            periodo = "de " + dataIni + " a " + dataFim;
        }
        String sMovimentacoes = "";
        for (String s : tiposMovSelecionadas) {
            sMovimentacoes += s + ", ";
        }
        sMovimentacoes = sMovimentacoes.substring(0, sMovimentacoes.length() - 2);

        String sConsulta = "";

        if (selectOperacao.equalsIgnoreCase("IGUAL")) {
            sConsulta = "Produtores que relataram exatamente " + sValor + " ocorrências das movimentações selecionadas";
        } else if (selectOperacao.equalsIgnoreCase("MENOR")) {
            sConsulta = "Produtores que relataram menos que " + sValor + " ocorrências das movimentações selecionadas";
        } else if (selectOperacao.equalsIgnoreCase("MAIOR")) {
            sConsulta = "Produtores que relataram mais que " + sValor + " ocorrências das movimentações selecionadas";
        }
        //Coloca na sessão dados para o cabeçalho do relatório.
        session.setAttribute("sConsulta", sConsulta.toUpperCase());
        session.setAttribute("sTipoAnimal", sTipoAnimal.toUpperCase());
        session.setAttribute("sMovimetacoes", sMovimentacoes.toUpperCase());
        session.setAttribute("periodo", periodo);
        session.setAttribute("listaProdutores", produtoresResult);
        return "/visit/relatorio_qt_gerado_prods_movims.jsp";
    }

    private int getOcorrenciasDaMovimentacao(Movimentacao movimentacao, String nomeMovimentacao) {
        if (movimentacao == null || nomeMovimentacao == null) {
            return 0;
        }
        if (nomeMovimentacao.equals(ROUBADOS)) {
            return movimentacao.getRoubados();
        }
        if (nomeMovimentacao.equals(NASCIDOS)) {
            return movimentacao.getNascidos();
        }
        if (nomeMovimentacao.equals(COMPRADOS)) {
            return movimentacao.getComprados();
        }
        if (nomeMovimentacao.equals(VENDIDOS)) {
            return movimentacao.getVendidos();
        }
        if (nomeMovimentacao.equals(MORTOS)) {
            return movimentacao.getMortos();
        }
        return 0;
    }

    private int getOcorrenciasDaMovimentaçaoPorTipoAnimal(Movimentacao movimentacao, TipoAnimal tipoAnimal, String nomeMovimentacao) {
        if (movimentacao == null || nomeMovimentacao == null || tipoAnimal == null) {
            return 0;
        }
        if (movimentacao.getTipoAnimal().equals(tipoAnimal)) {
            return getOcorrenciasDaMovimentacao(movimentacao, nomeMovimentacao);
        }
        return 0;
    }

    private boolean isCompatibleWithCondtions(Integer[] qtdeMovimentacoes, String selectOperacao, Integer valor) {
        if (selectOperacao.equals("MAIOR")) {
            for (Integer inValor : qtdeMovimentacoes) {
                if (inValor.intValue() <= valor.intValue()) {
                    return false;
                }
            }
            return true;
        } else if (selectOperacao.equals("MENOR")) {
            for (Integer inValor : qtdeMovimentacoes) {
                if (inValor.intValue() >= valor.intValue()) {
                    return false;
                }
            }
            return true;
        } else if (selectOperacao.equals("IGUAL")) {
            for (Integer inValor : qtdeMovimentacoes) {
                if (inValor.intValue() != valor.intValue()) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }
}
